﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using NDF.Data.EntityFramework;
using NDF.Data.EntityFramework.Practices;
using NDF.Utilities;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Core.EntityClient;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Migrations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace NDF.Tests.Framework.EntityFramework
{
    [TestClass]
    public class EFUnitTest
    {
        [TestMethod]
        public void TestMethod1()
        {
            using (UADemoEntities ctx = new UADemoEntities())
            {
                //var users = from u in ctx.Users
                //            orderby u.Code
                //            select u;

                var userType = typeof(Unit);
                var property = userType.GetProperties().First(p => p.Name == "Name");
                var delegateType = typeof(Func<,>).MakeGenericType(userType, property.PropertyType);
                var getMethod = property.GetGetMethod().CreateDelegate(delegateType);

                var orderbyMethod = typeof(System.Linq.Enumerable).GetMethods().First(m => m.Name == "OrderBy" && m.IsGenericMethod && m.GetParameters().Length == 2).MakeGenericMethod(userType, property.PropertyType);
                
                //var users = ctx.Users.OrderBy(method);
                var users = orderbyMethod.Invoke(null, new object[] { ctx.Users, getMethod }) as IOrderedEnumerable<Unit>;

                //Console.WriteLine(users);
                foreach (var u in users)
                {
                    Console.WriteLine(u.ToJson());
                }
            }
        }


        [TestMethod]
        public void TestMethod2()
        {
            UADemoEntities ctx = new UADemoEntities();
            using (EntityAccessor accessor = new EntityAccessor(ctx))
            {
                //var set = ctx.Set(typeof(User));
                //Console.WriteLine(set.ElementType);
                //User u = ctx.Set(typeof(User)).Find(Guid.Parse("0423CC64-1C60-49EF-9A94-4F9835AB6E99")) as User;
                //Console.WriteLine(u.ToJson());
                User user = new User
                {
                    Key = Guid.Parse("0423CC64-1C60-49EF-9A94-4F9835AB6E90"),
                    Code = "004",
                    Name = "赵六",
                    Password = "123456",
                    Sex = 1,
                    Birthday = Convert.ToDateTime("1984-11-11"),
                    ID = 1,
                    Flag = 0,
                    CreateDate = Convert.ToDateTime("2014-11-05 15:00:01.267"),
                    CreateUserID = 0,
                    ModifyDate = Convert.ToDateTime("2014-11-05 15:00:01.267"),
                    ModifyUserID = 0,
                    Remark = null
                };
                accessor.AddOrUpdate(user);
                Console.WriteLine(accessor.SaveChanges());

                //ctx.Set<User>().AddOrUpdate(user);

                //var data = accessor.QueryPaging<Power>(0, 3, "ID");
                //Console.WriteLine(data.ToJson());

                //accessor.DeleteAll(typeof(Session));

                //Console.WriteLine(accessor.DbContext.IsDefinedEntity<Unit>());

                //Console.WriteLine(accessor.QueryAll(typeof(Power)).ToJson());

                //Console.WriteLine(accessor.DbContext.GetTableName(typeof(AppPower)));
            }
        }

        [TestMethod]
        public void TestMethod3()
        {
            var array = typeof(System.Linq.Enumerable).GetMethods().Where(m =>
            {
                var parameters = m.GetParameters();
                var parameter = parameters[1];
                var parameterType = parameter.ParameterType;
                var parameterTypeBase = parameterType.GetGenericTypeDefinition();

                return m.Name == "OrderBy" && m.IsGenericMethod && m.GetParameters().Length == 2;
            });

            foreach (var item in array)
            {
                Console.WriteLine(item);
            }
        }

        [TestMethod]
        public void TestMethod4()
        {
            Unit u = new Unit() { ID = 1, Name = "张三", Age = 23, CreateDate = DateTime.Now };
            ParameterExpression paramExpr = Expression.Parameter(typeof(Unit));
            Expression expr = Expression.PropertyOrField(paramExpr, "Name");

            Console.WriteLine(paramExpr.Type);
            Console.WriteLine(expr.Type);
        }


        [TestMethod]
        public void TestMethod5()
        {
            //MemberInfo member = typeof(Unit).GetMember("ID").FirstOrDefault(m => m.MemberType == MemberTypes.Property || m.MemberType == MemberTypes.Field);
            //Console.WriteLine(member.DeclaringType);

            var unit = new Unit() { ID = 1, Name = "张三", Age = 23, CreateDate = DateTime.Now };

            Console.WriteLine(Funcs.Func(typeof(Unit), "Name").DynamicInvoke(unit));
        }

        [TestMethod]
        public void TestMethod6()
        {
            MethodInfo method = typeof(System.Data.Entity.Migrations.DbSetMigrationsExtensions).GetMethods().First(m =>
            {
                if (m.Name != "AddOrUpdate" || !m.IsGenericMethod)
                    return false;
                ParameterInfo[] parameters = m.GetParameters();
                return parameters.Length == 2
                                && parameters[0].ParameterType.IsGenericType && parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(IDbSet<>)
                                && parameters[1].ParameterType.IsArray && parameters[1].ParameterType.ContainsGenericParameters;
            });
            Console.WriteLine(method);
        }

        [TestMethod]
        public void TestMethod7()
        {
            UADemoEntities ctx = new UADemoEntities();
            using (EntityAccessor<User> accessor = new EntityAccessor<User>(ctx))
            {
                User user = new User
                {
                    Key = Guid.Parse("0423CC64-1C60-49EF-9A94-4F9835AB6E99"),
                    Code = "004",
                    Name = "赵六",
                    Password = "123456",
                    Sex = 1,
                    Birthday = Convert.ToDateTime("1984-11-11"),
                    ID = 1,
                    Flag = 0,
                    CreateDate = Convert.ToDateTime("2014-11-05 15:00:01.267"),
                    CreateUserID = 0,
                    ModifyDate = Convert.ToDateTime("2014-11-05 15:00:01.267"),
                    ModifyUserID = 0,
                    Remark = null
                };
                //accessor.AddOrUpdate(user);
                //Console.WriteLine(accessor.SaveChanges());
                DbSet set = ctx.Set(typeof(User));

                Console.WriteLine(set.ToGeneric().Count());
            }
        }

        [TestMethod]
        public void TestMethod8()
        {
            UADemoEntities ctx = new UADemoEntities();
            //ctx.TruncateTable<Unit>();


            //Console.WriteLine(ctx.GetTableName(typeof(User)));
            //MetadataWorkspace metadata = ctx.GetObjectContext().MetadataWorkspace;
            //EntityContainer container = metadata.GetItems<EntityContainer>(DataSpace.SSpace).FirstOrDefault();
            //if (container == null)
            //    throw new InvalidConstraintException("获取实体数据上下文对象中的 实体容器对象失败，无法获取其 EntityContainer。");


            //Console.WriteLine(metadata.GetItems<EntityType>(DataSpace.CSpace).Count);
            //Console.WriteLine(metadata.GetItems<EntityType>(DataSpace.CSSpace).Count);
            //Console.WriteLine(metadata.GetItems<EntityType>(DataSpace.OCSpace).Count);
            //Console.WriteLine(metadata.GetItems<EntityType>(DataSpace.OSpace).Count);
            //Console.WriteLine(metadata.GetItems<EntityType>(DataSpace.SSpace).Count);


            //IEnumerable<EntitySet> tables = container.EntitySets.Where(set =>
            //    !set.MetadataProperties.Contains("Type") || set.MetadataProperties["Type"].ToString() == "Tables");

            //foreach (EntitySet set in tables)
            //{
                
            //}


            //foreach (var set in ctx.GetEntitySets())
            //{
            //    Console.WriteLine(set.Name);
            //}

            //Console.WriteLine(typeof(User).Name);
            //Console.WriteLine(ctx.GetTableName(typeof(User)));
        }
    }


    public class Unit
    {
        public int ID { get; set; }

        public string Name { get; set; }

        public int Age;

        public DateTime CreateDate { get; set; }
    }
}
